package com.ybkj.daijia.server.service.impl;

import com.ybkj.daijia.chart.DriverTimeVo;
import com.ybkj.daijia.common.Pager;
import com.ybkj.daijia.common.Principal;
import com.ybkj.daijia.page.Page;
import com.ybkj.daijia.page.Pageable;
import com.ybkj.daijia.page.impl.PageImpl;
import com.ybkj.daijia.page.impl.PageRequest;
import com.ybkj.daijia.server.mapper.DriverMapper;
import com.ybkj.daijia.server.mapper.DriverTimeDayMapper;
import com.ybkj.daijia.server.mapper.DriverTimeMonthMapper;
import com.ybkj.daijia.server.mapper.DriverTimeYearMapper;
import com.ybkj.daijia.server.model.Driver;
import com.ybkj.daijia.server.model.DriverTime;
import com.ybkj.daijia.server.model.DriverTimeDay;
import com.ybkj.daijia.server.model.DriverTimeMonth;
import com.ybkj.daijia.server.model.DriverTimeYear;
import com.ybkj.daijia.server.service.DriverTimeService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class DefaultDriverTimeService implements DriverTimeService {

    @Autowired
    private DriverTimeYearMapper driverTimeYearMapper;

    @Autowired
    private DriverTimeMonthMapper driverTimeMonthMapper;

    @Autowired
    private DriverTimeDayMapper driverTimeDayMapper;

    @Autowired
    private DriverMapper driverMapper;

    @Transactional(rollbackFor = Exception.class)
    public synchronized void driverTimeOnline(Driver driver, Calendar calendar) {
        DriverTimeYear driverTimeYear = driverTimeYearMapper
            .selectByYearAndDriver(calendar.get(Calendar.YEAR), driver.getId());
        if (null == driverTimeYear) {
            driverTimeYear = new DriverTimeYear();
            driverTimeYear.setDriverId(driver.getId());
            driverTimeYear.setDriverRealName(driver.getRealname());
            driverTimeYear.setDriverUserName(driver.getUsername());
            driverTimeYear.setCompanyId(driver.getCompanyId());
            driverTimeYear.setTotalTime(0);
            driverTimeYear.setYear(calendar.get(Calendar.YEAR));
            driverTimeYearMapper.insertRecord(driverTimeYear);

            for (int m = 1; m <= 12; m++) {
                DriverTimeMonth driverTimeMonth = new DriverTimeMonth();
                driverTimeMonth.setMonth(m);
                driverTimeMonth.setTotalTime(0);
                driverTimeMonth.setYearId(driverTimeYear.getId());
                driverTimeMonthMapper.insertRecord(driverTimeMonth);
            }

            DriverTimeMonth thisDriverTimeMonth = driverTimeMonthMapper
                .selectByYearAndMonth(driverTimeYear.getId(), calendar.get(Calendar.MONTH) + 1);

            DriverTimeDay driverTimeDay = new DriverTimeDay();
            driverTimeDay.setDay(calendar.get(Calendar.DAY_OF_MONTH));
            driverTimeDay.setTotalTime(0);
            driverTimeDay.setMonthId(thisDriverTimeMonth.getId());
            driverTimeDay.setLastOnlined(calendar.getTime());
            driverTimeDayMapper.insertRecord(driverTimeDay);

        } else {

            DriverTimeMonth thisDriverTimeMonth = driverTimeMonthMapper
                .selectByYearAndMonth(driverTimeYear.getId(), calendar.get(Calendar.MONTH) + 1);
            DriverTimeDay driverTimeDay = driverTimeDayMapper
                .selectByMonthAndDay(thisDriverTimeMonth.getId(),
                    calendar.get(Calendar.DAY_OF_MONTH));
            if (null != driverTimeDay) {
                driverTimeDay.setLastOnlined(calendar.getTime());
                driverTimeDayMapper.updateLastOnlined(driverTimeDay);
            } else {
                driverTimeDay = new DriverTimeDay();
                driverTimeDay.setDay(calendar.get(Calendar.DAY_OF_MONTH));
                driverTimeDay.setTotalTime(0);
                driverTimeDay.setMonthId(thisDriverTimeMonth.getId());
                driverTimeDay.setLastOnlined(calendar.getTime());
                driverTimeDayMapper.insertRecord(driverTimeDay);
            }
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public void driverTimeOffline(Driver driver, Calendar calendar) {
        DriverTimeYear driverTimeYear = driverTimeYearMapper
            .selectByYearAndDriver(calendar.get(Calendar.YEAR), driver.getId());
        if (null != driverTimeYear) {
            DriverTimeMonth driverTimeMonth = driverTimeMonthMapper
                .selectByYearAndMonth(driverTimeYear.getId(), calendar.get(Calendar.MONTH) + 1);
            DriverTimeDay driverTimeDay = driverTimeDayMapper
                .selectByMonthAndDay(driverTimeMonth.getId(), calendar.get(Calendar.DAY_OF_MONTH));
            if (null != driverTimeDay) {
                Long start = driverTimeDay.getLastOnlined().getTime();
                Long end = calendar.getTime().getTime();
                Long wrokeTime = (end - start) / 60000; // 1000*60 分钟

                driverTimeDay.setTotalTime(driverTimeDay.getTotalTime() + wrokeTime);
                if (driverTimeDay.getTotalTime() > (60 * 24)) {// 一天1440分钟
                    driverTimeDay.setTotalTime(60 * 24);
                }
                driverTimeDayMapper.updateByPrimaryKey(driverTimeDay);

                driverTimeMonth.setTotalTime(driverTimeMonth.getTotalTime() + wrokeTime);
                if (driverTimeMonth.getTotalTime() > (60 * 24 * calendar
                    .getActualMaximum(Calendar.MONTH))) {// 一月
                    driverTimeMonth
                        .setTotalTime(60 * 24 * calendar.getActualMaximum(Calendar.MONTH));
                }
                driverTimeMonthMapper.updateByPrimaryKey(driverTimeMonth);

                driverTimeYear.setTotalTime(driverTimeYear.getTotalTime() + wrokeTime);
                if (driverTimeYear.getTotalTime() > (60 * 24 * calendar
                    .getActualMaximum(Calendar.DAY_OF_YEAR))) {// 一年
                    driverTimeYear
                        .setTotalTime(60 * 24 * calendar.getActualMaximum(Calendar.DAY_OF_YEAR));
                }
                driverTimeYearMapper.updateByPrimaryKey(driverTimeYear);

            }

        }

    }

    @Override
    public Page<DriverTimeVo> pageDriverTime(Calendar calendar, String name, Long companyId) {

        Pageable pageable = new PageRequest(Pager.getPage(), Pager.getLimit());

        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();

        String likeName = null;
        if (StringUtils.isNotBlank(name)) {
            likeName = "%" + name + "%";
        }

        if (!principal.isCompanyType()) {
            companyId = principal.getCompanyId();
        }

        List<DriverTimeYear> content = driverTimeYearMapper
            .selectByParams(calendar.get(Calendar.YEAR), likeName, companyId, Pager.getOffset(),
                Pager.getLimit());
        Long total = driverTimeYearMapper
            .countByParams(calendar.get(Calendar.YEAR), likeName, companyId);

        List<DriverTimeVo> list = new ArrayList<DriverTimeVo>();

        if (total > 0) {

            for (DriverTimeYear driverTimeYear : content) {
                DriverTimeVo driverTimeVo = new DriverTimeVo();
                driverTimeVo.setId(driverTimeYear.getDriverId());
                driverTimeVo.setRealname(driverTimeYear.getDriverRealName());
                driverTimeVo.setUsername(driverTimeYear.getDriverUserName());

                DriverTimeMonth driverTimeMonth = driverTimeMonthMapper
                    .selectByYearAndMonth(driverTimeYear.getId(), calendar.get(Calendar.MONTH) + 1);
                // driverTimeVo.setWorkTime(new
                // BigDecimal(Double.valueOf(driverTimeMonth.getTotalTime())/60).setScale(2,
                // BigDecimal.ROUND_UP).doubleValue());

                List<Double> dayWorkTime = new ArrayList<Double>();
                for (int i = 1; i <= calendar.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
                    // if(i<=calendar.get(Calendar.DAY_OF_MONTH)){
                    DriverTimeDay driverTimeDay = driverTimeDayMapper
                        .selectByMonthAndDay(driverTimeMonth.getId(), i);
                    if (null != driverTimeDay) {
                        BigDecimal dayTime = new BigDecimal(
                            Double.valueOf(driverTimeDay.getTotalTime()) / 60)
                            .setScale(2, BigDecimal.ROUND_UP);
                        dayWorkTime.add(dayTime.doubleValue());
                        driverTimeVo
                            .setWorkTime(driverTimeVo.getWorkTime() + dayTime.doubleValue());
                    } else {
                        dayWorkTime.add(0d);
                    }
                    // }
                    // else{
                    // dayWorkTime.add(0d);
                    // }
                }
                driverTimeVo.setWorkTime(
                    new BigDecimal(driverTimeVo.getWorkTime()).setScale(2, BigDecimal.ROUND_UP)
                        .doubleValue());
                driverTimeVo.setDayWorkTime(dayWorkTime);
                list.add(driverTimeVo);
            }
        }

        return new PageImpl<DriverTimeVo>(list, pageable, total);
    }

    @Override
    public Long countDriverTime(Integer year, String name, Long companyId) {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();

        String likeName = null;
        if (StringUtils.isNotBlank(name)) {
            likeName = "%" + name + "%";
        }

        if (!principal.isCompanyType()) {
            companyId = principal.getCompanyId();
        }

        return driverTimeYearMapper.countByParams(year, likeName, companyId);
    }

    @Override
    public List<DriverTimeVo> exportDriverTime(Calendar calendar, String name, Long companyId,
        boolean allAmount, Integer amounts) {

        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();

        String likeName = null;
        if (StringUtils.isNotBlank(name)) {
            likeName = "%" + name + "%";
        }

        if (!principal.isCompanyType()) {
            companyId = principal.getCompanyId();
        }

        Integer offset = 0;
        Integer limit = amounts;
        if (allAmount) {
            offset = null;
            limit = null;
        }

        List<DriverTimeYear> content = driverTimeYearMapper
            .selectByParams(calendar.get(Calendar.YEAR), likeName, companyId, offset, limit);

        List<DriverTimeVo> list = new ArrayList<DriverTimeVo>();

        if (!CollectionUtils.isEmpty(content)) {

            for (DriverTimeYear driverTimeYear : content) {
                DriverTimeVo driverTimeVo = new DriverTimeVo();
                driverTimeVo.setId(driverTimeYear.getDriverId());
                driverTimeVo.setRealname(driverTimeYear.getDriverRealName());
                driverTimeVo.setUsername(driverTimeYear.getDriverUserName());

                DriverTimeMonth driverTimeMonth = driverTimeMonthMapper
                    .selectByYearAndMonth(driverTimeYear.getId(), calendar.get(Calendar.MONTH) + 1);
                // driverTimeVo.setWorkTime(new
                // BigDecimal(Double.valueOf(driverTimeMonth.getTotalTime())/60).setScale(2,
                // BigDecimal.ROUND_HALF_UP).doubleValue());

                List<Double> dayWorkTime = new ArrayList<Double>();
                for (int i = 1; i <= calendar.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
                    if (i <= calendar.get(Calendar.DAY_OF_MONTH)) {
                        DriverTimeDay driverTimeDay = driverTimeDayMapper
                            .selectByMonthAndDay(driverTimeMonth.getId(), i);
                        if (null != driverTimeDay) {
                            BigDecimal dayTime = new BigDecimal(
                                Double.valueOf(driverTimeDay.getTotalTime()) / 60)
                                .setScale(2, BigDecimal.ROUND_UP);
                            dayWorkTime.add(dayTime.doubleValue());
                            driverTimeVo
                                .setWorkTime(driverTimeVo.getWorkTime() + dayTime.doubleValue());
                        } else {
                            dayWorkTime.add(0d);
                        }
                    } else {
                        dayWorkTime.add(0d);
                    }
                }
                driverTimeVo.setWorkTime(
                    new BigDecimal(driverTimeVo.getWorkTime()).setScale(2, BigDecimal.ROUND_UP)
                        .doubleValue());
                driverTimeVo.setDayWorkTime(dayWorkTime);
                list.add(driverTimeVo);
            }
        }

        return list;
    }

    @Override
    public List<DriverTime> listDriverTimeByDate(Date start, Date end) {
        return driverTimeYearMapper.listDriverTimeByDate(start, end);
    }

    @Override
    public Date getDriverLastOnlineTime(Long driverId, Calendar instance) {
        int year = instance.get(Calendar.YEAR);
        int month = instance.get(Calendar.MONTH) + 1;
        int day = instance.get(Calendar.DAY_OF_MONTH);
        DriverTimeYear driverTimeYear = driverTimeYearMapper.selectByYearAndDriver(year, driverId);
        if (driverTimeYear != null) {
            DriverTimeMonth driverTimeMonth = driverTimeMonthMapper
                .selectByYearAndMonth(driverTimeYear.getId(), month);
            if (driverTimeMonth != null) {
                DriverTimeDay driverTimeDay = driverTimeDayMapper
                    .selectByMonthAndDay(driverTimeMonth.getId(), day);
                if (driverTimeDay == null) {
                    return new Date();
                }
                return driverTimeDay.getLastOnlined();
            }
        }
        return new Date();
    }

}
